package com.amirarcane.lockscreen.andrognito.pinlockview;

import com.amirarcane.lockscreen.ResourceTable;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.ListContainer;
import ohos.agp.components.element.Element;
import ohos.agp.text.Font;
import ohos.app.Context;

/**
 * Represents a numeric lock view which can used to taken numbers as input.
 * The length of the input can be customized using PinLockView#setPinLength(int), the default value being 4
 * <p/>
 * It can also be used as dial pad for taking number inputs.
 * Optionally,IndicatorDots can be attached to this view to indicate the length of the input taken
 * Created by aritraroy on 31/05/16.
 */

public class PinLockView extends ListContainer implements ListContainer.ItemClickedListener{

    private static final int DEFAULT_PIN_LENGTH = 4;
    private String mPin = "";
    private int mPinLength;
    private int mHorizontalSpacing, mVerticalSpacing;
    private Component mTextColor;
    private int mDeleteButtonPressedColor;
    private int mTextSize, mButtonSize, mDeleteButtonWidthSize, mDeleteButtonHeightSize;
    private Element mButtonBackgroundDrawable;
    private Element mDeleteButtonDrawable;
    private boolean mShowDeleteButton;

    private IndicatorDots mIndicatorDots;
    private PinLockAdapter mAdapter;
    private PinLockListener mPinLockListener;
    private CustomizationOptionsBundle mCustomizationOptionsBundle;



    private PinLockAdapter.OnNumberClickListener mOnNumberClickListener
            = new PinLockAdapter.OnNumberClickListener() {
        @Override
        public void onNumberClicked(int keyValue) {

            if (mPin.length() < getPinLength()) {
                mPin = mPin.concat(String.valueOf(keyValue));

                if (isIndicatorDotsAttached()) {
                    mIndicatorDots.updateDot(mPin.length());
                }

                if (mPin.length() == 1) {
                    mAdapter.setPinLength(mPin.length());
                    mAdapter.notifyDataSetItemChanged(mAdapter.getCount()-1);
                }

                if (mPinLockListener != null) {
                    if (mPin.length() == mPinLength) {
                        mPinLockListener.onComplete(mPin);
                    } else {
                        mPinLockListener.onPinChange(mPin.length(), mPin);
                    }
                }
            } else {
                if (!isShowDeleteButton()) {
                    resetPinLockView();
                    mPin = mPin.concat(String.valueOf(keyValue));

                    if (isIndicatorDotsAttached()) {
                        mIndicatorDots.updateDot(mPin.length());
                    }

                    if (mPinLockListener != null) {
                        mPinLockListener.onPinChange(mPin.length(), mPin);
                    }

                } else {
                    if (mPinLockListener != null) {
                        mPinLockListener.onComplete(mPin);
                    }
                }
            }
        }
    };

    private PinLockAdapter.OnDeleteClickListener mOnDeleteClickListener
            = new PinLockAdapter.OnDeleteClickListener() {
        @Override
        public void onDeleteClicked() {

            if (mPin.length() > 0) {

                mPin = mPin.substring(0, mPin.length() - 1);

                if (isIndicatorDotsAttached()) {
                    mIndicatorDots.updateDot(mPin.length());
                }

                if (mPin.length() == 0) {
                    mAdapter.setPinLength(mPin.length());
                    mAdapter.notifyDataSetItemChanged(mAdapter.getCount() - 1);
                }

                if (mPinLockListener != null) {
                    if (mPin.length() == 0) {
                        mPinLockListener.onEmpty();
                        clearInternalPin();
                    } else {
                        mPinLockListener.onPinChange(mPin.length(), mPin);
                    }
                }
            } else {
                if (mPinLockListener != null) {
                    mPinLockListener.onEmpty();
                }
            }
        }

        @Override
        public void onDeleteLongClicked() {
            resetPinLockView();
            if (mPinLockListener != null) {
                mPinLockListener.onEmpty();
            }
        }
    };


    public PinLockView(Context context) {
        super(context);
        init(null, 0);
    }

    public PinLockView(Context context, AttrSet attrs) {
        super(context, attrs);
        init(attrs, 0);
    }

    private void init(AttrSet attributeSet, int defStyle) {

        try {
            mPinLength=(int)ResourceUtils.getDimensionInPx(getContext(),DEFAULT_PIN_LENGTH);
            mHorizontalSpacing = (int) ResourceUtils.getDimensionInPx(getContext(),40);
            mVerticalSpacing = (int) ResourceUtils.getDimensionInPx(getContext(),18);
            mTextColor = findComponentById(ResourceTable.Color_text_numberpressed);
            mTextSize = (int) ResourceUtils.getDimensionInPx(getContext(),25);
            mButtonSize = (int) ResourceUtils.getDimensionInPx(getContext(),60);
            mDeleteButtonWidthSize = (int) ResourceUtils.getDimensionInPx(getContext(),39);
            mDeleteButtonHeightSize = (int) ResourceUtils.getDimensionInPx(getContext(),27);
        } finally {
        }

        mCustomizationOptionsBundle = new CustomizationOptionsBundle();
        mCustomizationOptionsBundle.setTextColor(mTextColor);
        mCustomizationOptionsBundle.setTextSize(mTextSize);
        mCustomizationOptionsBundle.setButtonSize(mButtonSize);
        mCustomizationOptionsBundle.setButtonBackgroundDrawable(mButtonBackgroundDrawable);
        mCustomizationOptionsBundle.setDeleteButtonDrawable(mDeleteButtonDrawable);
        mCustomizationOptionsBundle.setDeleteButtonWidthSize(mDeleteButtonWidthSize);
        mCustomizationOptionsBundle.setDeleteButtonHeightSize(mDeleteButtonHeightSize);
        mCustomizationOptionsBundle.setShowDeleteButton(mShowDeleteButton);
        mCustomizationOptionsBundle.setDeleteButtonPressesColor(mDeleteButtonPressedColor);

        initView();
    }

    private void initView() {

        mAdapter = new PinLockAdapter(getContext());

        mAdapter.setOnItemClickListener(mOnNumberClickListener);
       mAdapter.setOnDeleteClickListener(mOnDeleteClickListener);
        mAdapter.setCustomizationOptions(mCustomizationOptionsBundle);

        this.setItemProvider(mAdapter);


    }

    public void setTypeFace(Font typeFace) {
        mAdapter.setTypeFace(typeFace);
    }

    /**
     * Sets a {@link PinLockListener} to the to listen to pin update events
     *
     * @param pinLockListener the listener
     */
    public void setPinLockListener(PinLockListener pinLockListener) {
        this.mPinLockListener = pinLockListener;
    }

    /**
     * Get the length of the current pin length
     *
     * @return the length of the pin
     */
    public int getPinLength() {
        return mPinLength;
    }

    /**
     * Sets the pin length dynamically
     *
     * @param pinLength the pin length
     */
    public void setPinLength(int pinLength) {
        this.mPinLength = pinLength;

        if (isIndicatorDotsAttached()) {
            mIndicatorDots.setPinLength(pinLength);
        }
    }


    /**
     * Is the delete button shown
     *
     * @return returns true if shown, false otherwise
     */
    public boolean isShowDeleteButton() {
        return mShowDeleteButton;
    }



    private void clearInternalPin() {
        mPin = "";
    }

    /**
     * Resets the {@link PinLockView}, clearing the entered pin
     * and resetting the {@link IndicatorDots} if attached
     */
    public void resetPinLockView() {

        clearInternalPin();

        mAdapter.setPinLength(mPin.length());
        mAdapter.notifyDataSetItemChanged(mAdapter.getCount() - 1);

        if (mIndicatorDots != null) {
            mIndicatorDots.updateDot(mPin.length());
        }
    }

    /**
     * Returns true if {@link IndicatorDots} are attached to {@link PinLockView}
     *
     * @return true if attached, false otherwise
     */
    public boolean isIndicatorDotsAttached() {
        return mIndicatorDots != null;
    }

    /**
     * Attaches {@link IndicatorDots} to {@link PinLockView}
     *
     * @param mIndicatorDots the view to attach
     */
    public void attachIndicatorDots(IndicatorDots mIndicatorDots) {
        this.mIndicatorDots = mIndicatorDots;
    }

    @Override
    public void onItemClicked(ListContainer listContainer, Component component, int i, long l) {
    }

}
